package myJs.user.workflow.featureSelection.svm

import com.softwaremill.quicklens._
import myJs.Implicits._
import myJs.cps.{InputCp, RSelectMulCp, SelectCp}

import myJs.myPkg.reactHookForm.{ReactHookForm, UseFormRT, UseFormStateOptions}
import myJs.tool.Tool
import myJs.tool.Tool._
import shared.pojo.WorkflowMission._

import scala.collection.immutable.SeqMap
import scala.scalajs.js

import japgolly.scalajs.react.vdom.all._
import japgolly.scalajs.react._
import japgolly.scalajs.react.React.Fragment
import japgolly.scalajs.react.util.EffectCatsEffect._
import myJs.myPkg.Hooks._
import cats.effect._
import myJs.Implicits._
import myJs.Utils._

/** Created by yz on 3/11/2020
  */
object SvmCp {

  case class Props(
      curI: Int,
      data: EachSvmData,
      dataChange: EachSvmData => SyncIO[Unit],
      dataModifyF: (EachSvmData => EachSvmData) => SyncIO[Unit],
      fsData: FsData
  ) {
    @inline def render: VdomElement = {
      Component(this)
    }
  }

  val Component = ScalaFnComponent[Props] { props =>
    val curTool = Svm
    val namePrefix = s"svm.${props.curI}"

    object FTool {

      def scaleMethodChange = (v: String) => {
        val newData = props.data.modify(_.scaleMethod).setTo(v)
        props.dataChange(newData)
      }

      def groupsModifyF = (v: List[String]) => {
        val newData = modifyLens[EachSvmData](_.groups).setTo(v)
        props.dataModifyF(newData)
      }

      def kernelChange = (v: String) => {
        val newData = props.data.modify(_.kernel).setTo(v)
        props.dataChange(newData)
      }

      def costChange = (v: String) => {
        val newData = props.data.modify(_.cost).setTo(v)
        props.dataChange(newData)
      }

      def toleranceChange = (v: String) => {
        val newData = props.data.modify(_.tolerance).setTo(v)
        props.dataChange(newData)
      }

      def epsilonChange = (v: String) => {
        val newData = props.data.modify(_.epsilon).setTo(v)
        props.dataChange(newData)
      }

      def gammaChange = (v: String) => {
        val newData = props.data.modify(_.gamma).setTo(v)
        props.dataChange(newData)
      }

      def coef0Change = (v: String) => {
        val newData = props.data.modify(_.coef0).setTo(v)
        props.dataChange(newData)
      }

      def degreeChange = (v: String) => {
        val newData = props.data.modify(_.degree).setTo(v)
        props.dataChange(newData)
      }

      def topMChange = (v: String) => {
        val newData = props.data.modify(_.topM).setTo(v)
        props.dataChange(newData)
      }

    }

    val formState = ReactHookForm.useFormState(options =
      UseFormStateOptions(
        name = namePrefix
      )
    )

    useEffect(
     SyncIO{
        Tool.refreshNodeColor(props.data.nodeId, formState, namePrefix)
      },
      List(formState)
    )
    val dataMatrixGroups = props.fsData.dataMatrix.groups
    useEffect(
      {
        FTool.groupsModifyF(dataMatrixGroups)
      },
      List(dataMatrixGroups)
    )
    val groupMap = dataMatrixGroups.optionMap
    val kernelMap = SeqMap(
      "linear" -> "linear",
      "polynomial" -> "polynomial",
      "radial" -> "radial",
      "sigmoid" -> "sigmoid"
    )

    div(
      RSelectMulCp.Props(
        value = props.data.groups,
        label = messages("groups"),
        name = s"${namePrefix}.groups",
        optionMap = groupMap,
        onChange = FTool.groupsModifyF
      ).render,
      SelectCp.Props(
        value = props.data.scaleMethod,
        label = messages("scaleMethod"),
        name = s"${namePrefix}.scaleMethod",
        optionMap = scaleMethodMap,
        onChange = FTool.scaleMethodChange
      ).render,
      SelectCp.Props(
        value = props.data.kernel,
        label = messages("kernelFunction"),
        name = s"${namePrefix}.kernel",
        optionMap = kernelMap,
        onChange = FTool.kernelChange
      ).render,
      InputCp.Props(
        value = props.data.cost,
        show = true,
        label = "cost",
        name = s"${namePrefix}.cost",
        onChange = FTool.costChange
      ).render,
      InputCp.Props(
        value = props.data.tolerance,
        show = true,
        label = "tolerance",
        name = s"${namePrefix}.tolerance",
        onChange = FTool.toleranceChange
      ).render,
      InputCp.Props(
        value = props.data.epsilon,
        show = true,
        label = "epsilon",
        name = s"${namePrefix}.epsilon",
        onChange = FTool.epsilonChange
      ).render,
      InputCp.Props(
        value = props.data.gamma,
        show = List("polynomial", "sigmoid", "radial").exists(props.data.kernel == _),
        label = "gamma",
        name = s"${namePrefix}.gamma",
        onChange = FTool.gammaChange
      ).render,
      InputCp.Props(
        value = props.data.coef0,
        show = List("polynomial", "sigmoid").exists(props.data.kernel == _),
        label = "coef0",
        name = s"${namePrefix}.coef0",
        onChange = FTool.coef0Change
      ).render,
      InputCp.Props(
        value = props.data.degree,
        show = (props.data.kernel == "polynomial"),
        label = "degree",
        name = s"${namePrefix}.degree",
        onChange = FTool.degreeChange
      ).render,
      InputCp.Props(
        value = props.data.topM,
        show = true,
        label = messages("selectionTopM"),
        name = s"${namePrefix}.topM",
        onChange = FTool.topMChange
      ).render
    )

  }

}
